﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using DocumentFormat.OpenXml.Packaging;

namespace TISS_Add_in
{
    public static class LoteGuias
    {
        /// <summary>
        /// Cria objeto ws_loteGuias a ser enviado para o webservice da operadora.
        /// A lista guiasPath deve conter um array de string para cada guia:
        /// A posição [0] do array deve estar o endereço da guia;
        /// As demais posições deve conter o endereço das guias de outras despesas, caso existam.
        /// </summary>
        /// <param name="codPrestadorOrigem">código do Prestador</param>
        /// <param name="regANSDestino">registro na ANS da operadora</param>
        /// <param name="numeroLote">número do lote a ser enviado</param>
        /// <param name="guiasPath">endereço (Path) de cada guia</param>
        /// <returns></returns>
        public static docTissLoteGuias.ws_loteGuias GeraLoteGuias(long codPrestadorOrigem, string regANSDestino, string numeroLote, List<string[]> guiasPath, TipoGuia tipoGuia, tipoTransacao TipoTransacao)
        {
            docTissLoteGuias.ws_loteGuias loteGuias = new TISS_Add_in.docTissLoteGuias.ws_loteGuias();            
            string nomeGuia = "";
            loteGuias.cabecalho =
                (docTissLoteGuias.cabecalhoTransacao)Cabecalho.GeraCabecalho(codPrestadorOrigem, regANSDestino, TipoTransacao);

            if (loteGuias.cabecalho != null)
            {
                try
                {
                    loteGuias.loteGuias = new docTissLoteGuias.ct_loteGuias();
                    loteGuias.loteGuias.numeroLote = numeroLote;

                    loteGuias.loteGuias.guias = new TISS_Add_in.docTissLoteGuias.ct_loteGuiasGuias();

                    object itemLoteGuias = null;

                    if (tipoGuia <= TipoGuia.Odontologia)
                    {
                        itemLoteGuias = new docTissLoteGuias.ct_guiasGuiaFaturamento();
                        ((docTissLoteGuias.ct_guiasGuiaFaturamento)itemLoteGuias).Items = new Object[guiasPath.Count];
                    }
                    else
                    {
                        itemLoteGuias = new docTissLoteGuias.ct_guiasGuiaRevisaoGlosa();
                        ((docTissLoteGuias.ct_guiasGuiaRevisaoGlosa)itemLoteGuias).Items = new Object[guiasPath.Count];
                    }

                    Object[] itemGuias = new Object[guiasPath.Count];

                    int guiaIndex = 0;

                    foreach (string[] guiaArray in guiasPath)
                    {
                        nomeGuia = Path.GetFileName(guiaArray[0]);
                        object guia = ExtraiGuiaCustomXML(guiaArray, tipoGuia);
                        if (guia != null)
                        {
                            itemGuias[guiaIndex] = guia;
                            guiaIndex++;
                        }
                        else
                        {
                            itemGuias = new object[0];
                            break;
                        }
                    }

                    if (itemGuias != null)
                    {
                        if (tipoGuia <= TipoGuia.Odontologia)
                            ((docTissLoteGuias.ct_guiasGuiaFaturamento)itemLoteGuias).Items = itemGuias;
                        else
                            ((docTissLoteGuias.ct_guiasGuiaRevisaoGlosa)itemLoteGuias).Items = itemGuias;

                        loteGuias.loteGuias.guias.Item = itemLoteGuias;

                        #region Rodapé

                        //Fechando a Guia de Consulta e Serializando em Memória

                        Stream streamMensagem = XMLUtils.Serializa(loteGuias, null);
                        streamMensagem.Position = 0;

                        //Fim da Mensagem: HASH
                        loteGuias.hash = AddinUtils.CalculateMD5Hash(streamMensagem);

                        #endregion
                    }
                    return loteGuias;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            return null;
        }

        public static TipoGuiaCustomXML ExtraiGuiaCustomXML(string pathGuia, params string[] path)
        {
            TipoGuiaCustomXML retorno = new TipoGuiaCustomXML();

            using (WordprocessingDocument wdoc = WordprocessingDocument.Open(pathGuia, false))
            {
                //Buscando o CustomXML referente a Guia
                foreach (CustomXmlPart cPart in wdoc.MainDocumentPart.CustomXmlParts)
                {
                    //Carrega a parte
                    XmlDocument xdoc = new XmlDocument();
                    xdoc.Load(cPart.GetStream());

                    //Encontrou?
                    if (xdoc.InnerXml.Contains("guiaConsulta"))
                    {
                        retorno.customXML = geraGuiaConsulta(xdoc);
                        retorno.tipoGuia = TipoGuia.Consulta;
                    }
                    else if (xdoc.InnerXml.Contains("guiaSP_SADT"))
                    {
                        retorno.customXML = geraGuiaSP_SADT(xdoc, path);
                        retorno.tipoGuia = TipoGuia.SP_SADT;
                    }
                    else if (xdoc.InnerXml.Contains("guiaResumoInternacao"))
                    {
                        retorno.customXML = geraGuiaResumoInternacao(xdoc, path);
                        retorno.tipoGuia = TipoGuia.Resumo_Internação;
                    }
                    else if (xdoc.InnerXml.Contains("guiaHonorarioIndividual"))
                    {
                        retorno.customXML = geraGuiaHonorarioIndividual(xdoc);
                        retorno.tipoGuia = TipoGuia.Honorário_Individual;
                    }
                    else if (xdoc.InnerXml.Contains("guiaOdontologia"))
                    {
                        retorno.customXML = geraGuiaOdontologia(xdoc);
                        retorno.tipoGuia = TipoGuia.Odontologia;
                    }
                    else if (xdoc.InnerXml.Contains("guiaConsultaReapresentacao"))
                    {
                        retorno.customXML = geraGuiaConsultaReapresentacao(xdoc);
                        retorno.tipoGuia = TipoGuia.Consulta_Reapresentação;
                    }
                    else if (xdoc.InnerXml.Contains("guiaSP_SADTReapresentacao"))
                    {
                        retorno.customXML = geraGuiaSP_SADTReapresentacao(xdoc, path);
                        retorno.tipoGuia = TipoGuia.SP_SADT_Reapresentação;
                    }
                    else if (xdoc.InnerXml.Contains("guiaResumoInternacaoReapresentacao"))
                    {
                        retorno.customXML = geraGuiaResumoInternacaoReapresentacao(xdoc, path);
                        retorno.tipoGuia = TipoGuia.Resumo_Internação_Reapresentação;
                    }
                    else if (xdoc.InnerXml.Contains("guiaHonorarioIndividualReapresentacao"))
                    {
                        retorno.customXML = geraGuiaHonorarioIndividualReapresentacao(xdoc);
                        retorno.tipoGuia = TipoGuia.Honorário_Individual_Reapresentação;
                    }
                    else if (xdoc.InnerXml.Contains("guiaOdontologiaReapresentacao"))
                    {
                        retorno.customXML = geraGuiaOdontologiaReapresentacao(xdoc);
                        retorno.tipoGuia = TipoGuia.Odontologia_Reapresentação;
                    }                    
                    
                }
            }
            return retorno;
        }
        /// <summary>
        /// Extrai o objeto ct_guia do arquivo docx.
        /// guiaArray[0] = path da guia;
        /// guiaArray[i>0] = path guia outras despesas.
        /// </summary>
        /// <param name="guiaArray"></param>
        /// <returns></returns>
        public static object ExtraiGuiaCustomXML(string[] guiaArray, TipoGuia tipoGuia)
        {
            //Os parametros podem ser ExtraiGuiaCustomXML(TipoGuia tipoGuia, params string[] guiasPath),
            //assim é possível passar apenas uma string caso nao existam guias de outras despesas.
            string filePath = guiaArray[0];
            using (WordprocessingDocument wdoc = WordprocessingDocument.Open(filePath, false))
            {
                //Buscando o CustomXML referente a Guia
                foreach (CustomXmlPart cPart in wdoc.MainDocumentPart.CustomXmlParts)
                {
                    //Carrega a parte
                    XmlDocument xdoc = new XmlDocument();
                    xdoc.Load(cPart.GetStream());

                    //Encontrou?
                    if (xdoc.InnerXml.Contains("http://www.ans.gov.br/padroes/tiss/schemas"))
                    {
                        try
                        {
                            switch (tipoGuia)
                            {
                                case TipoGuia.Consulta:
                                    return geraGuiaConsulta(xdoc);
                                case TipoGuia.SP_SADT:
                                    return geraGuiaSP_SADT(xdoc, guiaArray);
                                case TipoGuia.Resumo_Internação:
                                    return geraGuiaResumoInternacao(xdoc, guiaArray);
                                case TipoGuia.Honorário_Individual:
                                    return geraGuiaHonorarioIndividual(xdoc);
                                case TipoGuia.Odontologia:
                                    return geraGuiaOdontologia(xdoc);
                                case TipoGuia.Consulta_Reapresentação:
                                    return geraGuiaConsultaReapresentacao(xdoc);
                                case TipoGuia.SP_SADT_Reapresentação:
                                    return geraGuiaSP_SADTReapresentacao(xdoc, guiaArray);
                                case TipoGuia.Resumo_Internação_Reapresentação:
                                    return geraGuiaResumoInternacaoReapresentacao(xdoc, guiaArray);
                                case TipoGuia.Honorário_Individual_Reapresentação:
                                    return geraGuiaHonorarioIndividualReapresentacao(xdoc);
                                case TipoGuia.Odontologia_Reapresentação:
                                    return geraGuiaOdontologiaReapresentacao(xdoc);
                            }
                        }
                        catch (Exception ex)
                        {
                            if (ex.Message.Contains("XML"))
                            {
                                MessageBox.Show("O lote não pode ser gerado:\nA guia '" + Path.GetFileName(filePath) + "' contém problemas de validação em sua estrutura.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                            }
                            else
                            {
                                MessageBox.Show(ex.Message, "Mensagem não enviada!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                            }
                        }
                    }
                }
            }
            return null;
        }

        private static object geraGuiaConsulta(XmlDocument xdoc)
        {
            if (xdoc.InnerXml.Contains("guiaConsulta"))
            {
                byte[] buffer = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdoc));
                Stream str = new MemoryStream(buffer);

                return XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_guiaConsulta), XMLUtils.ElementRootWithANSnamespace("guiaConsulta"));
            }
            return null;
        }

        private static object geraGuiaSP_SADT(XmlDocument xdoc, string[] guiaArray)
        {
            if (xdoc.InnerXml.Contains("guiaSP_SADT"))
            {
                byte[] buffer = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdoc));
                Stream str = new MemoryStream(buffer);
                docTissLoteGuias.ct_guiaSP_SADT gspsadt = (docTissLoteGuias.ct_guiaSP_SADT)XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_guiaSP_SADT), XMLUtils.ElementRootWithANSnamespace("guiaSP_SADT"));

                for (int i = 1; i < guiaArray.Length; i++)
                {
                    string OutrasDespesasPath = guiaArray[i];

                    using (WordprocessingDocument wdocOutrasDepesas = WordprocessingDocument.Open(OutrasDespesasPath, false))
                    {
                        //Buscando o CustomXML referente a Guia
                        foreach (CustomXmlPart cPartOutrasDepesas in wdocOutrasDepesas.MainDocumentPart.CustomXmlParts)
                        {
                            //Carrega a parte
                            XmlDocument xdocOutrasDepesas = new XmlDocument();
                            xdocOutrasDepesas.Load(cPartOutrasDepesas.GetStream());

                            //Encontrou?
                            if (xdocOutrasDepesas.InnerXml.Contains("outrasDespesas"))
                            {
                                byte[] bufferOutrasDepesas = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdocOutrasDepesas));
                                Stream strOutrasDepesas = new MemoryStream(bufferOutrasDepesas);

                                docTissLoteGuias.ct_outrasDespesas gOutrasDespesas = (docTissLoteGuias.ct_outrasDespesas)XMLUtils.Deserializa(strOutrasDepesas, typeof(docTissLoteGuias.ct_outrasDespesas), XMLUtils.ElementRootWithANSnamespace("outrasDespesas"));

                                gspsadt.outrasDespesas = gOutrasDespesas;
                            }
                        }
                    }
                }
                return (object)gspsadt;
            }
            return null;
        }

        private static object geraGuiaResumoInternacao(XmlDocument xdoc, string[] guiaArray)
        {
            if (xdoc.InnerXml.Contains("guiaResumoInternacao"))
            {
                byte[] buffer = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdoc));
                Stream str = new MemoryStream(buffer);

                docTissLoteGuias.ct_guiaResumoInternacao gResumoInternacao = (docTissLoteGuias.ct_guiaResumoInternacao)XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_guiaResumoInternacao), XMLUtils.ElementRootWithANSnamespace("guiaResumoInternacao"));

                for (int i = 1; i < guiaArray.Length; i++)
                {
                    string OutrasDespesasPath = guiaArray[i];

                    using (WordprocessingDocument wdocOutrasDepesas = WordprocessingDocument.Open(OutrasDespesasPath, false))
                    {
                        //Buscando o CustomXML referente a Guia
                        foreach (CustomXmlPart cPartOutrasDepesas in wdocOutrasDepesas.MainDocumentPart.CustomXmlParts)
                        {
                            //Carrega a parte
                            XmlDocument xdocOutrasDepesas = new XmlDocument();
                            xdocOutrasDepesas.Load(cPartOutrasDepesas.GetStream());

                            //Encontrou?
                            if (xdocOutrasDepesas.InnerXml.Contains("outrasDespesas"))
                            {
                                //Retira os campos não obrigatórios que não foram preenchidos
                                //string normalizedXML = XMLUtils.GetNormalizedXMLString(xdoc);
                                byte[] bufferOutrasDepesas = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdocOutrasDepesas));
                                Stream strOutrasDepesas = new MemoryStream(bufferOutrasDepesas);
                                docTissLoteGuias.ct_outrasDespesas gOutrasDespesas = (docTissLoteGuias.ct_outrasDespesas)XMLUtils.Deserializa(strOutrasDepesas, typeof(docTissLoteGuias.ct_outrasDespesas), XMLUtils.ElementRootWithANSnamespace("outrasDespesas"));

                                gResumoInternacao.outrasDespesas = gOutrasDespesas;
                            }
                        }
                    }
                }

                return (object)gResumoInternacao;
            }
            return null;
        }

        private static object geraGuiaHonorarioIndividual(XmlDocument xdoc)
        {
            if (xdoc.InnerXml.Contains("guiaHonorarioIndividual"))
            {
                byte[] buffer = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdoc));
                Stream str = new MemoryStream(buffer);

                return XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_guiaHonorarioIndividual), XMLUtils.ElementRootWithANSnamespace("guiaHonorarioIndividual"));
            }
            return null;
        }

        private static object geraGuiaConsultaReapresentacao(XmlDocument xdoc)
        {
            if (xdoc.InnerXml.Contains("guiaConsultaReapresentacao"))
            {
                byte[] buffer = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdoc));
                Stream str = new MemoryStream(buffer);

                return XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_guiaConsultaReapresentacao), XMLUtils.ElementRootWithANSnamespace("guiaConsultaReapresentacao"));
            }
            return null;
        }

        private static object geraGuiaSP_SADTReapresentacao(XmlDocument xdoc, string[] guiaArray)
        {
            if (xdoc.InnerXml.Contains("guiaSP_SADTReapresentacao"))
            {
                byte[] buffer = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdoc));
                Stream str = new MemoryStream(buffer);
                docTissLoteGuias.ct_guiaSP_SADTReapresentacao gspsadt = (docTissLoteGuias.ct_guiaSP_SADTReapresentacao)XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_guiaSP_SADT), XMLUtils.ElementRootWithANSnamespace("guiaSP_SADTReapresentacao"));

                for (int i = 1; i < guiaArray.Length; i++)
                {
                    string OutrasDespesasPath = guiaArray[i];

                    using (WordprocessingDocument wdocOutrasDepesas = WordprocessingDocument.Open(OutrasDespesasPath, false))
                    {
                        //Buscando o CustomXML referente a Guia
                        foreach (CustomXmlPart cPartOutrasDepesas in wdocOutrasDepesas.MainDocumentPart.CustomXmlParts)
                        {
                            //Carrega a parte
                            XmlDocument xdocOutrasDepesas = new XmlDocument();
                            xdocOutrasDepesas.Load(cPartOutrasDepesas.GetStream());

                            //Encontrou?
                            if (xdocOutrasDepesas.InnerXml.Contains("guiaOutrasDespesasRevisao"))
                            {
                                byte[] bufferOutrasDepesas = Encoding.GetEncoding("ISO-8859-1").GetBytes(xdocOutrasDepesas.InnerXml);
                                Stream strOutrasDepesas = new MemoryStream(bufferOutrasDepesas);
                                docTissLoteGuias.ct_outrasDespesasRevisao gOutrasDespesas = (docTissLoteGuias.ct_outrasDespesasRevisao)XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_outrasDespesasRevisao), XMLUtils.ElementRootWithANSnamespace("guiaOutrasDespesasRevisao"));

                                gspsadt.outrasDespesas = gOutrasDespesas;
                            }
                        }
                    }
                }
                return (object)gspsadt;
            }
            return null;
        }

        private static object geraGuiaResumoInternacaoReapresentacao(XmlDocument xdoc, string[] guiaArray)
        {
            if (xdoc.InnerXml.Contains("guiaResumoInternacaoReapresentacao"))
            {
                byte[] buffer = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdoc));
                Stream str = new MemoryStream(buffer);

                docTissLoteGuias.ct_guiaResumoInternacaoReapresentacao gResumoInternacao = (docTissLoteGuias.ct_guiaResumoInternacaoReapresentacao)XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_guiaResumoInternacaoReapresentacao), XMLUtils.ElementRootWithANSnamespace("guiaResumoInternacaoReapresentacao"));

                for (int i = 1; i < guiaArray.Length; i++)
                {
                    string OutrasDespesasPath = guiaArray[i];

                    using (WordprocessingDocument wdocOutrasDepesas = WordprocessingDocument.Open(OutrasDespesasPath, false))
                    {
                        //Buscando o CustomXML referente a Guia
                        foreach (CustomXmlPart cPartOutrasDepesas in wdocOutrasDepesas.MainDocumentPart.CustomXmlParts)
                        {
                            //Carrega a parte
                            XmlDocument xdocOutrasDepesas = new XmlDocument();
                            xdocOutrasDepesas.Load(cPartOutrasDepesas.GetStream());

                            //Encontrou?
                            if (xdocOutrasDepesas.InnerXml.Contains("guiaOutrasDespesasRevisao"))
                            {
                                //Retira os campos não obrigatórios que não foram preenchidos
                                //string normalizedXML = XMLUtils.GetNormalizedXMLString(xdoc);
                                byte[] bufferOutrasDepesas = Encoding.GetEncoding("ISO-8859-1").GetBytes(xdocOutrasDepesas.InnerXml);
                                Stream strOutrasDepesas = new MemoryStream(bufferOutrasDepesas);
                                docTissLoteGuias.ct_outrasDespesasRevisao gOutrasDespesas = (docTissLoteGuias.ct_outrasDespesasRevisao)XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_outrasDespesasRevisao), XMLUtils.ElementRootWithANSnamespace("guiaOutrasDespesasRevisao"));

                                gResumoInternacao.outrasDespesas = gOutrasDespesas;
                            }
                        }
                    }
                }

                return (object)gResumoInternacao;
            }
            return null;
        }

        private static object geraGuiaHonorarioIndividualReapresentacao(XmlDocument xdoc)
        {
            if (xdoc.InnerXml.Contains("guiaHonorarioIndividualReapresentacao"))
            {
                byte[] buffer = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdoc));
                Stream str = new MemoryStream(buffer);

                return XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_guiaHonorarioIndividualReapresentacao), XMLUtils.ElementRootWithANSnamespace("guiaHonorarioIndividualReapresentacao"));
            }
            return null;
        }

        private static object geraGuiaOdontologia(XmlDocument xdoc)
        {
            if (xdoc.InnerXml.Contains("guiaOdontologia"))
            {
                byte[] buffer = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdoc));
                Stream str = new MemoryStream(buffer);

                return XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_guiaOdontologia), XMLUtils.ElementRootWithANSnamespace("guiaOdontologia"));
            }
            return null;
        }

        private static object geraGuiaOdontologiaReapresentacao(XmlDocument xdoc)
        {
            if (xdoc.InnerXml.Contains("guiaOdontologiaReapresentacao"))
            {
                byte[] buffer = Encoding.GetEncoding("ISO-8859-1").GetBytes(XMLUtils.GetNormalizedXMLString(xdoc));
                Stream str = new MemoryStream(buffer);

                return XMLUtils.Deserializa(str, typeof(docTissLoteGuias.ct_guiaTratamentoOdontologicoReapresentacao), XMLUtils.ElementRootWithANSnamespace("guiaOdontologiaReapresentacao"));
            }
            return null;
        }
        
    }
}
